import { exec } from "child_process";
import { join } from "path";
import ping from "ping";
import { isDev } from "../utils";
import { deviceInfoCmd } from "./cmdConfig";

const cmdExec = (cmd) => {
  return new Promise((resolve, reject) => {
    exec(
      cmd,
      {
        cwd: join(
          process.cwd(),
          isDev() ? "./plugins/" : "./resources/plugins/"
        ),
      },
      (error, stdout, stderr) => {
        if (error) {
          reject(error);
          return;
        }
        resolve(stdout);
      }
    );
  });
};

export const getDeviceInfoByHdc = async (SN) => {
  const device = {};
  try {
    const info = await cmdExec(deviceInfoCmd.hdc.getDeviceInfo(SN));
    const infos = info
      .split("\r\n")
      .filter(Boolean)
      .map((item) => item.trim());
    device["CPU Arch"] = infos[0];
    device["Device Name"] = infos[1];
    device["Device Type"] = infos[2];
    device["OS"] = infos[3];

    const CPUFreq = await cmdExec(deviceInfoCmd.hdc.getCPUFreq(SN));
    let cpuFreq = "";
    CPUFreq.split("\r\n")
      .filter(Boolean)
      .forEach((item) => {
        cpuFreq += Number(item.split("=")[1]) / 1000 + "MHZ-";
      });
    device["CPU Freq"] = cpuFreq;

    const CPUCoreNum = await cmdExec(deviceInfoCmd.hdc.getCPUCoreNum(SN));
    device["CPU CoreNum"] = CPUCoreNum;

    const CPUType = await cmdExec(deviceInfoCmd.hdc.getCPUType(SN));
    // device["CPU Type"] = CPUType;

    const GPUFreq = await cmdExec(deviceInfoCmd.hdc.getGPUFreq(SN));
    device["GPU Freq"] = Number(GPUFreq.split("=")[1]) / 1000 / 1000 + "GHZ";

    const ip = await cmdExec(deviceInfoCmd.hdc.getIp(SN));
    const ipArr =
      ip
        .split("\r\n")
        .filter(Boolean)
        .map((item) => item.trim()) || [];
    if (ipArr && ipArr[0]) {
      const temp = ipArr[0].split(" ") || [];
      if (temp && temp[1]) {
        const arr = temp[1].split(":") || [];
        if (arr && arr[1]) {
          device["Ip"] = arr[1];
        }
      }
    }
  } catch (err) {
    console.log(err);
  }
  return device;
};

export const getDeviceInfoByAdb = async (SN) => {
  const device = {};
  try {
    const OpenGLInfo = await cmdExec(deviceInfoCmd.adb.getOpenGLInfo(SN));
    const OpenGLInfoArr = OpenGLInfo.split(",").map((item) => item.trim());
    device["GPU Type"] = `${OpenGLInfoArr[0].split(":")[1]} ${
      OpenGLInfoArr[1]
    }`;
    device["OpenGL"] = OpenGLInfoArr[2];

    const CPUArchInfo = await cmdExec(deviceInfoCmd.adb.getCPUArch(SN));
    device["CPU Arch"] = CPUArchInfo.trim();

    const CPUtypeInfo = await cmdExec(deviceInfoCmd.adb.getCPUType(SN));
    device["CPU Type"] = CPUtypeInfo.trim();

    const SystemVersionInfo = await cmdExec(
      deviceInfoCmd.adb.getSystemVersion(SN)
    );
    device["OS"] = SystemVersionInfo.trim();

    const CPUInfo = await cmdExec(deviceInfoCmd.adb.getCPUInfo(SN));
    device["CPU CoreNum"] = CPUInfo.split("\r\n")
      .find((item) => item.startsWith("CPU architecture"))
      .split(":")[1];

    const WinSize = await cmdExec(deviceInfoCmd.adb.getWinSize(SN));
    device["Resolution"] = WinSize.split("\r\n")[1].split(":")[1];

    const CPUFreq = await cmdExec(deviceInfoCmd.adb.getCPUFreq(SN));
    let cpuFreq = "";
    CPUFreq.split(" ").forEach((item) => {
      if (item !== "\r\n") {
        cpuFreq += Number(item) / 1000 + "MHZ-";
      }
    });
    device["CPU Freq"] = cpuFreq;

    const GPUFreq = await cmdExec(deviceInfoCmd.adb.getGPUFreq(SN));
    let gpuFreq = Number(GPUFreq) / 1000 / 1000 + "GHZ";
    device["GPU Freq"] = gpuFreq;

    const ip = await cmdExec(deviceInfoCmd.adb.getIp(SN));
    const ipArr =
      ip
        .split("\r\n")
        .filter(Boolean)
        .map((item) => item.trim()) || [];
    if (ipArr && ipArr[0]) {
      const temp = ipArr[0].split(" ") || [];
      if (temp && temp[1]) {
        const arr = temp[1].split(":") || [];
        if (arr && arr[1]) {
          device["Ip"] = arr[1];
        }
      }
    }
  } catch (err) {
    console.log(err);
  }
  return device;
};

export const getDeviceListByHdc = async () => {
  const deviceList = [];
  try {
    const stdout = await cmdExec(deviceInfoCmd.hdc.getDeviceList);
    if (!stdout.includes("Empty")) {
      const arr = stdout
        .split("\r\n")
        .filter(Boolean)
        .filter((device) => !device.startsWith("COM"));
      for (let i = 0; i < arr.length; i++) {
        const deviceInfos = arr[i].split("\t").filter(Boolean);
        if (deviceInfos[2] === "Offline") continue;
        const device = {
          SN: deviceInfos[0],
          "Device Name": "",
          "Device Type": "",
          OS: "",
          "CPU Type": "",
          "CPU Info": "",
          "CPU Arch": "",
          "CPU CoreNum": "",
          "CPU Freq": "",
          "GPU Type": "",
          OpenGL: "",
          "GPU Freq": "",
          Resolution: "",
        };
        const serialno =
          (await cmdExec(deviceInfoCmd.hdc.getSN(deviceInfos[0]))) || "";
        device["serialno"] = serialno.replace("\r\n", "");
        deviceList.push(device);
      }
    }
  } catch (err) {
    console.log(err);
  }
  return deviceList;
};

export const getDeviceListByAdb = async () => {
  const deviceList = [];
  try {
    const stdout = await cmdExec(deviceInfoCmd.adb.getDeviceList);
    const arr = stdout.split("\r\n").filter(Boolean);
    for (let i = 0; i < arr.length; i++) {
      const deviceInfos = arr[i].split(" ").filter(Boolean);
      if (deviceInfos.includes("device")) {
        const device = {
          SN: deviceInfos[0],
          "Device Name": "",
          "Device Type": "",
          OS: "",
          "CPU Type": "",
          "CPU Info": "",
          "CPU Arch": "",
          "CPU CoreNum": "",
          "CPU Freq": "",
          "GPU Type": "",
          OpenGL: "",
          Resolution: "",
        };
        for (let i = 2; i < deviceInfos.length; i++) {
          const [key, val] = deviceInfos[i].split(":");
          switch (key) {
            case "product":
              device["Device Name"] = val;
              break;
            case "model":
              device["Device Type"] = val;
              break;
            case "device":
              break;
            default:
              break;
          }
        }
        const serialno =
          (await cmdExec(deviceInfoCmd.adb.getSN(deviceInfos[0]))) || "";
        device["serialno"] = serialno.replace("\r\n", "");
        deviceList.push(device);
      }
    }
  } catch (err) {
    console.log(err);
  }
  return deviceList;
};

export const hdcConnectByUsb = async (SN) => {
  await cmdExec(deviceInfoCmd.hdc.connectByUsb(SN));
};

export const hdcConnectByWifi = async (SN, Ip) => {
  await cmdExec(deviceInfoCmd.hdc.connectByWifi(SN));
  await cmdExec(deviceInfoCmd.hdc.connectByPort(SN, Ip));
};

export const hdcExecReload = async (SN) => {
  await cmdExec(deviceInfoCmd.hdc.kill(SN));
  await cmdExec(deviceInfoCmd.hdc.restart(SN));
};

export const adbConnectByUsb = async (SN) => {
  await cmdExec(deviceInfoCmd.adb.connectByUsb(SN));
};

export const adbConnectByWifi = async (SN, Ip) => {
  await cmdExec(deviceInfoCmd.adb.connectByWifi(SN));
  await cmdExec(deviceInfoCmd.adb.connectByPort(SN, Ip));
};

export const adbExecReload = async (SN) => {
  await cmdExec(deviceInfoCmd.adb.kill(SN));
  await cmdExec(deviceInfoCmd.adb.restart(SN));
};

export const pingIP = async (ip) => {
  return new Promise((resolve) => {
    ping.sys.probe(ip, (isAlive) => {
      resolve(isAlive);
    });
  });
};
